package com.wgchao.authmanager.query;

import com.wgchao.authmanager.application.vo.RoleVo;
import com.wgchao.authmanager.infrastructure.convert.ev.RoleInfoConvertVo;
import com.wgchao.authmanager.infrastructure.jpa.entity.RoleInfo;
import com.wgchao.authmanager.infrastructure.jpa.entity.UserInfo;
import com.wgchao.authmanager.infrastructure.jpa.entity.UserRoleInfo;
import com.wgchao.authmanager.infrastructure.jpa.repository.RoleInfoJpaRepository;
import com.wgchao.authmanager.infrastructure.jpa.repository.UserInfoJpaReposotory;
import com.wgchao.authmanager.infrastructure.jpa.repository.UserRoleJpaRepository;
import com.wgchao.authmanager.infrastructure.resp.PageResult;
import com.wgchao.authmanager.query.specification.RoleCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: RoleInfoQuery
 * @author: wgchao
 * @createTime: 2020/5/7 4:38 PM
 * @Description: TODO
 */
@Service
public class RoleInfoQuery {
    @Autowired
    private UserInfoJpaReposotory userInfoJpaReposotory;
    @Autowired
    private RoleInfoJpaRepository roleInfoJpaRepository;
    @Autowired
    private RoleInfoConvertVo roleInfoConvertVo;
    @Autowired
    private UserRoleJpaRepository userRoleJpaRepository;

    /**
     * 按条件批量查询角色信息
     * @param criteria
     * @param operator
     * @return
     * @throws Exception
     */
    public PageResult<RoleVo> searchRolesOfCri(RoleCriteria criteria, String operator) throws Exception{
        Specification<RoleInfo> specification = new Specification<RoleInfo>() {
            @Override
            public Predicate toPredicate(Root<RoleInfo> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(criteria.getRoleName())){
                    Predicate predicate = criteriaBuilder.equal(root.get("roleName"), criteria.getRoleName());
                    predicateList.add(predicate);
                }
                if(criteria.getDisabled() != null){
                    if(criteria.getDisabled()){
                        Predicate predicate = criteriaBuilder.isTrue(root.get("disabled"));
                        predicateList.add(predicate);
                    }else{
                        Predicate predicate = criteriaBuilder.isFalse(root.get("disabled"));
                        predicateList.add(predicate);
                    }
                }
                UserInfo userInfo = userInfoJpaReposotory.findFirstByUname(operator);
                if(!"3702".equals(userInfo.getAgencyCode())){
                    Predicate predicate = criteriaBuilder.equal(root.get("agencyCode"), userInfo.getAgencyCode());
                    predicateList.add(predicate);
                }else{
                    if(!StringUtils.isEmpty(criteria.getAgencyCode())){
                        Predicate predicate = criteriaBuilder.equal(root.get("agencyCode"), criteria.getAgencyCode());
                        predicateList.add(predicate);
                    }
                }

                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);

                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };
        Pageable pageable = PageRequest.of(criteria.curr - 1, criteria.limit, Sort.by(Sort.Order.desc("createTime")));
        Page<RoleInfo> roleInfoPage = roleInfoJpaRepository.findAll(specification, pageable);
        if(roleInfoPage.isEmpty()){
            return new PageResult<RoleVo>(0, criteria.limit, criteria.curr, new ArrayList<>());
        }
        List<RoleVo> administratorVos = roleInfoPage.get().map(roleInfo -> {
            return roleInfoConvertVo.toModel(roleInfo);
        }).collect(Collectors.toList());
        return new PageResult<RoleVo>(roleInfoPage.getTotalElements(), criteria.limit, criteria.curr, administratorVos);
    }

    /**
     * 查询机构可用角色列表
     * @param agencyCode
     * @return
     */
    public List<RoleVo> searchRolesOfCanUseWithAgency(String agencyCode){
        List<RoleInfo> roleInfos = roleInfoJpaRepository.findAllByAgencyCodeAndDelIsFalseAndDisabledIsFalse(agencyCode);
        if(roleInfos==null || roleInfos.isEmpty()){
            return new ArrayList<>();
        }
        List<RoleVo> roleVos = roleInfos.stream().map(roleInfo -> {
            return roleInfoConvertVo.toModel(roleInfo);
        }).collect(Collectors.toList());

        return roleVos;
    }

    /**
     * 查询账户拥有角色
     * @param uname
     * @return
     */
    public List<RoleVo> searchRolesOfAdmin(String uname){
        List<UserRoleInfo> userRoleInfos = userRoleJpaRepository.findAllByUname(uname);
        if(userRoleInfos==null || userRoleInfos.isEmpty()){
            return new ArrayList<>();
        }
        List<RoleVo> roleVos = new ArrayList<>();
        for(UserRoleInfo userRoleInfo : userRoleInfos){
            RoleInfo roleInfo = roleInfoJpaRepository
                    .findFirstByAgencyCodeAndRoleNameAndDelIsFalse(userRoleInfo.getAgencyCode(), userRoleInfo.getRoleName());
            if(roleInfo != null && !roleInfo.isDisabled()){
                roleVos.add(roleInfoConvertVo.toModel(roleInfo));
            }
        }
        return roleVos;
    }
}
